package com.fjh.security.easy.starter.authority;

import com.fjh.security.easy.starter.authentication.exception.AccessPermissionException;
import com.fjh.security.easy.starter.util.HttpSessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author fanjh37
 * @since 2023/2/8 17:00
 */
@Component
@Aspect
@Slf4j
public class EasyPermissionAspect {

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Pointcut("@annotation(com.fjh.security.easy.starter.authority.EasyPermission)")
    public void permissionMethod() {
    }

    @Around("permissionMethod()")
    public Object permissionMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        EasyPermission permission = method.getAnnotation(EasyPermission.class);
        boolean result = check(permission);
        if (result) {
            return joinPoint.proceed();
        }
        accessDeniedHandler.handle(request,
                response, new AccessPermissionException("没有访问权限"));
        return null;
    }

    boolean check(EasyPermission easyPermission) {
        String permission;
        if (easyPermission.value().length == 0) {
            permission = request.getRequestURI().replaceFirst(request.getContextPath(), "");
        } else {
            permission = easyPermission.value()[0];
        }
        List<GrantedAuthority> authorities = (List<GrantedAuthority>) HttpSessionUtil.getUser().getAuthorities();
        return authorities.stream().anyMatch(y -> permission.equals(y.getAuthority()));
    }
}
